home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / DELPHI32 / COMM / ASYNCTIM / SOURCE.ZIP / AsyncTimer.pas < prev    next >
Pascal/Delphi Source File  |  1996-06-18  |  7KB  |  254 lines

  1. (*
  2.  
  3.   TAsyncTimer Component for Delphi 2.0
  4.   by Glen Why
  5.  
  6.   No rights reserved
  7.  
  8.   File version 1.00.00
  9.   
  10.   Version history
  11.  
  12.   1.00.00 - first one
  13.  
  14. *)
  15.  
  16. unit AsyncTimer;
  17.  
  18. interface
  19.  
  20. uses
  21.   Windows, Classes, SysUtils;
  22.  
  23. const
  24.  
  25. AsyncTimer_DefTimerThreadPriority = tpTimeCritical;
  26. AsyncTimer_DefTakerThreadPriority = tpHigher;
  27. AsyncTimer_DefInterval = 100;
  28. AsyncTimer_DefEnabled = false;
  29.  
  30. type
  31.  
  32.   EAsyncTimerError = class( Exception );
  33.  
  34.   TAsyncTimer = class(TComponent)
  35.   private
  36.     FTimerThreadPriority :TThreadPriority;
  37.     FTakerThreadPriority :TThreadPriority;
  38.     FOnTimer :TNotifyEvent;
  39.     FOnTimingFault :TNotifyEvent;
  40.     FInterval :Longint;
  41.     FTimerThread :THandle;
  42.     FTimerThreadID :THandle;
  43.     FTakerThread :THandle;
  44.     FTakerThreadID :THandle;
  45.     FEnabled :Boolean;
  46.     FTakerActive :Boolean;
  47.     FFinished :Boolean;
  48.     procedure InitTimerThread;
  49.     procedure DoneTimerThread;
  50.     procedure SetTimerThreadPriority( NewPriority :TThreadPriority );
  51.     procedure SetTakerThreadPriority( NewPriority :TThreadPriority );
  52.     procedure SetEnabled( NewState :Boolean );
  53.     procedure UpdateTimerThreadPriority;
  54.     procedure UpdateTakerThreadPriority;
  55.     procedure InitTakerThread;
  56.     procedure DoneTakerThread;
  57.   protected
  58.     procedure Timer; dynamic;
  59.     procedure TimingFault; dynamic;
  60.     procedure Loaded; override;
  61.   public
  62.     constructor Create( AnOwner :TComponent ); override;
  63.     destructor Destroy; override;
  64.   published
  65.     property Enabled :Boolean
  66.       read FEnabled write SetEnabled
  67.       default AsyncTimer_DefEnabled;
  68.     property Interval :Longint
  69.       read FInterval write FInterval
  70.       default AsyncTimer_DefInterval;
  71.     property OnTimer :TNotifyEvent
  72.       read FOnTimer write FOnTimer;
  73.     property OnTimingFault :TNotifyEvent
  74.       read FOnTimingFault write FOnTimingFault;
  75.     property TimerThreadPriority :TThreadPriority
  76.       read FTimerThreadPriority write SetTimerThreadPriority
  77.       default AsyncTimer_DefTimerThreadPriority;
  78.     property TakerThreadPriority :TThreadPriority
  79.       read FTakerThreadPriority write SetTakerThreadPriority
  80.       default AsyncTimer_DefTakerThreadPriority;
  81.   end;
  82.  
  83. implementation
  84.  
  85. const TimerThreadStackSize = $1000;
  86.  
  87. procedure TakerThreadProc( Timer :TAsyncTimer ); stdcall;
  88. begin
  89.   while not Timer.FFinished do
  90.    begin
  91.      Timer.FTakerActive := true;
  92.      Timer.Timer;
  93.      Timer.FTakerActive := false;
  94.      SuspendThread( Timer.FTakerThread );
  95.    end;
  96. end;
  97.  
  98.  
  99. procedure TimerThreadProc( Timer :TAsyncTimer ); stdcall;
  100. begin
  101.   while Timer.FInterval > 0 do
  102.    begin
  103.      if Timer.FTakerThread <> 0 then
  104.        if Timer.FTakerActive then Timer.TimingFault
  105.         else ResumeThread( Timer.FTakerThread );
  106.      sleep( Timer.FInterval );
  107.    end;
  108. end;
  109.  
  110. { TAsyncTimer }
  111.  
  112. constructor TAsyncTimer.Create( AnOwner :TComponent );
  113. begin
  114.  inherited Create( AnOwner );
  115.  FInterval := AsyncTimer_DefInterval;
  116.  FTimerThreadPriority := AsyncTimer_DefTimerThreadPriority;
  117.  FTakerThreadPriority := AsyncTimer_DefTakerThreadPriority;
  118.  FOnTimer := Nil;
  119.  FOnTimingFault := Nil;
  120.  FTimerThread := 0;
  121.  FTakerThread := 0;
  122.  FTakerActive := false;
  123.  FFinished := false;
  124.  FEnabled := AsyncTimer_DefEnabled;
  125. end;
  126.  
  127. destructor TAsyncTimer.Destroy;
  128. begin
  129.   DoneTimerThread;
  130.   DoneTakerThread;
  131.   inherited Destroy;
  132. end;
  133.  
  134. procedure TAsyncTimer.Loaded;
  135. begin
  136.  inherited Loaded;
  137.  InitTakerThread;
  138.  InitTimerThread;
  139. end;
  140.  
  141. procedure TAsyncTimer.SetTimerThreadPriority(
  142.  NewPriority :TThreadPriority );
  143. begin
  144.  if ( NewPriority <> FTimerThreadPriority ) then
  145.    begin
  146.     FTimerThreadPriority := NewPriority;
  147.     UpdateTimerThreadPriority;
  148.    end;
  149. end;
  150.  
  151. procedure TAsyncTimer.SetTakerThreadPriority(
  152.  NewPriority :TThreadPriority );
  153. begin
  154.  if ( NewPriority <> FTakerThreadPriority ) then
  155.    begin
  156.     FTakerThreadPriority := NewPriority;
  157.     UpdateTakerThreadPriority;
  158.    end;
  159. end;
  160.  
  161. procedure TAsyncTimer.SetEnabled( NewState :Boolean );
  162. begin
  163.  if ( FEnabled xor NewState ) then
  164.    begin
  165.     if ( ( [ csDesigning, csReading ] - ComponentState ) <> [] ) then
  166.      if NewState
  167.        then ResumeThread( FTimerThread )
  168.        else SuspendThread( FTimerThread );
  169.     FEnabled := NewState;
  170.    end;
  171. end;
  172.  
  173.  
  174. procedure TAsyncTimer.InitTimerThread;
  175. var CreationFlags :Longint;
  176. begin
  177.   if not ( csDesigning in ComponentState ) then { create thread at run-time only }
  178.     begin
  179.      CreationFlags := 0;
  180.      if not FEnabled then CreationFlags := CREATE_SUSPENDED;
  181.      FTimerThread := CreateThread( Nil, TimerThreadStackSize,
  182.       @TimerThreadProc, Self, CreationFlags, FTimerThreadID );
  183.      if ( FTimerThread = 0 ) then
  184.       raise EAsyncTimerError.Create( 'Thread creation error' );
  185.      UpdateTimerThreadPriority;
  186.     end;
  187. end;
  188.  
  189. procedure TAsyncTimer.DoneTimerThread;
  190. begin
  191.  if ( FTimerThread <> 0 ) then
  192.    begin
  193.      FInterval := -1;
  194.      ResumeThread( FTimerThread );
  195.      WaitForSingleObject( FTimerThread, INFINITE );
  196.      FTimerThread := 0;
  197.    end;
  198. end;
  199.  
  200. const
  201.  
  202.   Priorities: array [TThreadPriority] of Integer =
  203.    (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL,
  204.     THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL,
  205.     THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL);
  206.  
  207.  
  208. procedure TAsyncTimer.UpdateTimerThreadPriority;
  209. begin
  210.   SetThreadPriority( FTimerThread, Priorities[ FTimerThreadPriority ] );
  211. end;
  212.  
  213. procedure TAsyncTimer.UpdateTakerThreadPriority;
  214. begin
  215.   SetThreadPriority( FTakerThread, Priorities[ FTakerThreadPriority ] );
  216. end;
  217.  
  218. procedure TAsyncTimer.Timer;
  219. begin
  220.  if assigned( FOnTimer ) then FOnTimer( Self );
  221. end;
  222.  
  223. procedure TAsyncTimer.InitTakerThread;
  224. begin
  225.  if not ( csDesigning in ComponentState ) then { create thread at run-time only }
  226.    begin
  227.     FTakerActive := false;
  228.     FTakerThread := CreateThread( Nil, 0, @TakerThreadProc,
  229.      Self, CREATE_SUSPENDED, FTakerThreadID );
  230.     if ( FTakerThread = 0 ) then
  231.       raise EAsyncTimerError.Create( 'Timer event taker thread creation error' );
  232.     UpdateTakerThreadPriority;
  233.   end;
  234. end;
  235.  
  236. procedure TAsyncTimer.DoneTakerThread;
  237. begin
  238.  if ( FTakerThread <> 0 ) then
  239.    begin
  240.      FFinished := true;
  241.      ResumeThread( FTakerThread );
  242.      WaitForSingleObject( FTakerThread, INFINITE );
  243.      FTakerThread := 0;
  244.    end;
  245. end;
  246.  
  247. procedure TAsyncTimer.TimingFault;
  248. begin
  249.  if assigned( FOnTimingFault ) then FOnTimingFault( Self );
  250. end;
  251.  
  252.  
  253. end.
  254.